在進入到原型的第一章節時,說明了 JS 是以物件導向為基本設計概念的語言,在前幾章也陸續說明了原型作用機制與相關概念,以下就來實際檢視一下,物件導向在 JS 中究竟如何實現。
這裡再條列一次物件導向主要的幾個概念:
本篇會用 JS 實際案例說明封裝與抽象。
即是將相關的變數與方法放入物件中,減少程式碼複雜度,增加可復用性。
直接舉個例子:
let baseSalary = 30_000;
let overtime = 10;
let rate = 20;
function getWage(baseSalary, overtime, rate) {
return baseSalary + (overtime * rate)
}
let wage = getWage(baseSalary, overtime, rate);
以上程式碼毫無疑問是可以運作的,但有沒有更好的優化方法呢?讓程式碼更加便於維護,一看上去更加簡單明瞭。
可以看到這段程式碼中,baseSalary
、overtime
和 rate
這幾個變數和參數反覆出現,而其實它們僅使用於 getWage
內部,實際上可以進行「封裝」,將它們全部包在一起:
let employee = {
baseSalary: 30_000,
overtime: 10,
rate: 20,
getWage: function () {
return this.baseSalary + (this.overtime * this.rate)
}
}
let wage = employee.getWage();
進行封裝以後,不但調用的方式變得更簡單了,更能夠一目了然地知道 baseSalary
、overtime
和 rate
都附屬於同個物件 employee
本身,大大降低了程式碼的複雜度。
抽象的反面是具體,因此抽象化同時也可以說是「降低具體程度」,隱藏內部計算細節,只公開簡化過的必要操作。
抽象化具有以下優點:
抽象化前:
function Circle(radius) {
this.radius = radius;
this.defaultLocation = { x: 0, y: 0 };
this.doSomeCompute = function () {
console.log("Do some compute. Location:", this.defaultLocation);
}
this.draw = function () {
console.log("Start drawing.");
this.doSomeCompute()
}
}
const circle = new Circle(10);
circle.draw();
// Start drawing.
// Do some compute. Location: { x: 0, y: 0 }
// 僅用於內部計算,不應開放給外部的屬性
circle.defaultLocation = { x: 100, y: 100 }
circle.draw();
// Start drawing.
// Do some compute. Location: { x: 100, y: 100 }
把只用於內部的屬性和方法私有化:
function Circle(radius) {
this.radius = radius;
const defaultLocation = { x: 0, y: 0 };
const doSomeCompute = function () {
console.log("Do some compute. Location:", defaultLocation);
}
this.draw = function () {
console.log("Start drawing.");
doSomeCompute()
}
}
const circle = new Circle(10);
// 外部無法改動內部私有的屬性
circle.defaultLocation = { x: 100, y: 100 }
circle.draw();
// Start drawing.
// Do some compute. Location: { x: 0, y: 0 }